#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "clicklabel.h"
#include "logviewerdialog.h"
// #include "winutils.h"

#include <QDir>
#include <QPainter>
#include <QProcess>
#include <QFile>
#include <QMessageBox>
#include <QCoreApplication>
#include <QLabel>
#include <QTemporaryDir>
#include <QDebug>
#include <QRegularExpressionMatch>
#include <QVBoxLayout>
#include <QIntValidator>
#include <QTimer>
#include <QToolTip>
#include <QFileDialog>
#include <QDesktopServices>
#include <QRandomGenerator>
#include <QMutex>
#include <QMessageLogContext>
#include <Windows.h>
#include <QThread>
#include <QSettings>
#include <QStandardPaths>
#include <QInputDialog>
#ifdef Q_OS_WIN
#include <windows.h>
#include <shellapi.h>
#include <QFileInfo>
#include <QDir>
#endif
#include <searchdialog.h>

// 获取日志缓存的函数，使用函数静态变量
QString& getDebugLogBuffer() {
    static QString debugLogBuffer;
    return debugLogBuffer;
}

// 获取日志互斥锁的函数，使用函数静态变量
QMutex& getLogMutex() {
    static QMutex logMutex;
    return logMutex;
}

// 自定义消息处理器
void customMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    Q_UNUSED(context);
    QString logEntry;

    switch (type) {
    case QtDebugMsg:
        logEntry = QString("[DEBUG] %1").arg(msg);
        break;
    case QtInfoMsg:
        logEntry = QString("[INFO] %1").arg(msg);
        break;
    case QtWarningMsg:
        logEntry = QString("[WARNING] %1").arg(msg);
        break;
    case QtCriticalMsg:
        logEntry = QString("[CRITICAL] %1").arg(msg);
        break;
    case QtFatalMsg:
        logEntry = QString("[FATAL] %1").arg(msg);
        abort(); // 致命错误终止程序
    }

    QMutexLocker locker(&getLogMutex());
    getDebugLogBuffer() += logEntry + "\n";

    // 同时输出到控制台（开发调试用）
    fprintf(stderr, "%s\n", logEntry.toLocal8Bit().constData());
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowIcon(QIcon(":/img/disc.png"));
    this->setWindowTitle("Chs-Game300");
    this->setFixedSize(800, 600);


    ui->page_lineEdit->hide();
    ui->pageLabel->installEventFilter(this);        // 点击 QLabel 可触发事件
    this->installEventFilter(this);                 // MainWindow 安装自身为事件过滤器
    ui->page_lineEdit->installEventFilter(this);    // 监听失去焦点退出编辑

    labels = {
        ui->label, ui->label_2, ui->label_3, ui->label_4, ui->label_5,
        ui->label_6, ui->label_7, ui->label_8, ui->label_9, ui->label_10
    };

    QStringList sounds = {
        "qrc:/sound effect/Adventure Island SFX (13).wav", // index 0
        "qrc:/sound effect/UI SELECT.wav",                 // index 1 (用作悬停音效)
        "qrc:/sound effect/UI START.wav",                  // index 2
        "qrc:/sound effect/High1.wav",                     // index 3
        "qrc:/sound effect/swoosh-sound-effects.wav"
    };

    fontInit();         // 初始化字体
    initImagePaths();   // 初始化背景路径
    initAppPaths();     // 初始化模拟器路径
    loadRomFilePaths(); // 读取rom路径
    printDebugInfo();   // 打印调试信息
    showCurrentImage(); // 显示当前页
    initSoundEffects(sounds, sounds[1], 5, 0.3f); // 使用第2个音效作为池化悬停音效
    startGame();

}

MainWindow::~MainWindow()
{
    delete ui;
    saveSettings();
}

void MainWindow::toggleRememberLastPage(bool checked) // 槽函数实现是否勾选
{
    rememberlastPage = checked;
    saveSettings();
}

QString MainWindow::getLogBuffer()
{
    QMutexLocker locker(&getLogMutex());
    return getDebugLogBuffer();
}

void MainWindow::fontInit(){
    // 页数标签pageLabel
    ui->pageLabel->setToolTip("点击修改页码");
    ui->pageLabel->setCursor(Qt::PointingHandCursor);
    // 确保两个控件的内容边距一致
    ui->pageLabel->setContentsMargins(0, 0, 0, 0);
    ui->page_lineEdit->setContentsMargins(0, 0, 0, 0);
    ui->verticalLayout_2->setContentsMargins(10, 10, 10, 25);  // 边距: 左、上、右、下
    ui->verticalLayout_2->setSpacing(4);                        // 控件间距
    // 设置布局在父窗口中的拉伸因子
    QWidget* parentWidget =  ui->verticalLayout_2->parentWidget();
    QVBoxLayout* parentLayout = qobject_cast<QVBoxLayout*>(parentWidget->layout());
    if (parentLayout) {
        parentLayout->setStretchFactor(ui->verticalLayout_2, 2); // 设置拉伸因子
    }

    // 方法1: 使用字体度量计算高度
    QFontMetrics fontMetrics(ui->pageLabel->font());
    int textHeight = fontMetrics.height();
    int padding = 12; // 上下padding的总和(6px + 6px)
    int borderWidth = 2; // lineEdit的边框宽度
    // 设置相同的高度
    int uniformHeight = textHeight + padding + borderWidth;
    ui->pageLabel->setFixedHeight(uniformHeight);
    ui->page_lineEdit->setFixedHeight(uniformHeight);
    // 可选：让两个控件高度策略一致
    ui->pageLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    ui->page_lineEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);

    ui->pageLabel->setStyleSheet(R"(
        QLabel {
            font-size: 26px;
            color: #080000;
            padding: 6px 3px;
            border-radius: 6px;
            font-weight: bold;
            background-color: rgba(240, 240, 240, 0.7);
            border: 1px solid rgba(200, 200, 200, 0.7);
        }
        QLabel:hover {
            background-color: rgba(230, 230, 230, 0.9);
        }
    )");

    // 页码编辑标签page_lineEdit
    ui->page_lineEdit->setGeometry(ui->pageLabel->geometry());// 可选：设置 LineEdit 的位置为 label 的位置（如果 label 和 lineEdit 不重叠时需要）：
    // 页码输入框样式 - 增强交互体验
    ui->page_lineEdit->setStyleSheet(R"(
        QLineEdit {
            font-size: 24px;
            background-color: rgba(255, 255, 255, 0.9);
            padding: 3px 5px;
            height: 15px;
            border: 2px solid rgba(0, 161, 214, 0.8);
            border-radius: 6px;
            font-weight: bold;
            color: #080000;
            selection-background-color: rgba(0, 161, 214, 0.5);
            selection-color: white;
        }
        QLineEdit:focus {
            border-color: rgba(0, 161, 214, 1);
            background-color: white;
            outline: none;
        }
    )");
    ui->page_lineEdit->setToolTip(QString("输入1-%1之间的数字").arg(totalPages));

    for (QLabel* label : labels) {
        label->setCursor(Qt::PointingHandCursor); // 鼠标悬浮显示手指
        label->setStyleSheet(R"(
        ClickLabel {
            background-color: transparent;
            padding: 1px 8px;
            border-radius: 4px;
        }
        ClickLabel:hover {
            background-color: rgba(204, 255, 255, 0.7);
            color: #005bac;
            border-color: rgba(0, 161, 214, 1);
        }
        ClickLabel:pressed {
            color: #003a7f;
            background-color: rgba(190, 230, 255, 0.95);
            /* transform 被移除 */
        }
        )");


        QFont font = label->font();    // 获取当前字体
        font.setPointSize(20);         // 设置字体大小，比如22号字

        label->adjustSize();
        font.setWeight(QFont::Black);      // 更粗  设置加粗
        font.setFamily("SimHei"); // 设置字体类型（如微软雅黑）
        label->setFont(font);          // 应用字体到 label
    }


    QString btnStyle = R"(
    /* 普通状态下的按钮样式 */
    QPushButton {
        border: 2px solid rgba(0, 161, 214, 0.7);          /* 蓝色边框，70% 不透明度 */
        background-color: rgba(245, 252, 255, 0.8);        /* 淡蓝色背景，80% 不透明度 */
        font-size: 22px;                                    /* 字体大小 */
        color: #005bac;                                     /* 深蓝色文本 */
        padding: 2px 3px;                                  /* 内边距 */
        font-weight: bold;                                  /* 粗体文本 */
        border-radius: 6px;                                 /* 圆角边框 */
        min-width: 70px;                                    /* 最小宽度 */
    }
    QPushButton:hover {
        background-color: rgba(220, 240, 255, 0.9);      /* 更深的淡蓝色背景 */
        border-color: rgba(0, 161, 214, 1);              /* 完全不透明的边框 */
        color: #004a9f;                                   /* 更深的蓝色文本 */
        border-bottom-width: 3px; /* 模拟下沉效果 */
    }
    QPushButton:pressed {
        color: #003a7f;                                   /* 最深的蓝色文本 */
        background-color: rgba(190, 230, 255, 0.95);    /* 更深的蓝色背景 */
        border-bottom-width: 1px;
    }
    QPushButton:disabled {
        color: #aaa;                                      /* 灰色文本 */
        background-color: #f5f5f5;                       /* 浅灰色背景 */
        border-color: #ddd;                              /* 浅灰色边框 */
    }
        )";

    ui->prevButton->setStyleSheet(btnStyle);
    ui->nextButton->setStyleSheet(btnStyle);
    ui->prevButton->setCursor(Qt::PointingHandCursor);
    ui->nextButton->setCursor(Qt::PointingHandCursor);

    QString firstStyle = R"(
    QPushButton {
        background-color: rgba(0,161,214, 0.8);
        color: white;                      /* 字体颜色为 */
        font-weight: bold;
        border-radius: 5px;
    }
    QPushButton:hover {
        background-color: rgba(92, 179, 255, 0.85);  /* 设置透明度为50% */
    }
    )";


    ui->lastButton->setStyleSheet(firstStyle);
    ui->firstButton->setStyleSheet(firstStyle);
    ui->firstButton->setCursor(Qt::PointingHandCursor);
    ui->lastButton->setCursor(Qt::PointingHandCursor);
    ui->lastButton->setToolTip("最后一页");
    ui->firstButton->setToolTip("第一页");

    // 回车键输入完成时跳转
    connect(ui->page_lineEdit, &QLineEdit::editingFinished, this, [this]() {
        handlePageEdit();
    });
}

void MainWindow::setPage(int index)
{
    if (index < 0 || index >= totalPages || index == currentIndex) return; // 页面超出范围，或等于当前页不跳转
    currentIndex = index;
    ui->pageLabel->setText(QString("%1").arg(currentIndex + 1));
    ui->page_lineEdit->setText(QString::number(currentIndex + 1));

    showCurrentImage();
    playSoundByIndex(0);
}

bool MainWindow::eventFilter(QObject* obj, QEvent* event)
{
    // 【1】当点击 pageLabel（显示页码的标签）时，切换为可编辑状态
    if (obj == ui->pageLabel && event->type() == QEvent::MouseButtonPress) {
        // 设置 LineEdit 的初始值为当前页（+1 是因为显示页码从 1 开始）
        ui->page_lineEdit->setText(QString::number(currentIndex + 1));

        // 隐藏 label，显示输入框
        ui->pageLabel->hide();
        ui->page_lineEdit->show();
        ui->page_lineEdit->setFocus();  // 设置焦点到 lineEdit，用户可立即输入
        ui->page_lineEdit->selectAll(); // 选中所有文字，方便用户直接输入新数字

        return true;  // 表示事件已处理，不再向下传递
    }

    // 【2】如果点击主窗口任意空白区域，强制取消 page_lineEdit 的焦点，从而触发 focusOut
    if (obj == this && event->type() == QEvent::MouseButtonPress) {
        // 如果当前输入框可见，并且正处于编辑状态（拥有焦点）
        if (ui->page_lineEdit->isVisible() && ui->page_lineEdit->hasFocus()) {
            this->setFocus();  // 主窗口获取焦点，从而使 lineEdit 失焦
            // 注意：这一步会触发下面的 QEvent::FocusOut 处理逻辑
        }
    }

    // 【3】当输入框失去焦点（例如点击了空白或其他控件），恢复为原来的 label 显示
    if (obj == ui->page_lineEdit && event->type() == QEvent::FocusOut) {
        handlePageEdit();
        ui->page_lineEdit->hide();
        ui->pageLabel->show();
        return true;  // 表示事件已处理
    }

    // 【4】其他事件继续交由父类处理，不做拦截

    // 【5】如果是 QLabel，放行事件，不拦截（保证右键菜单能触发）
    if (QLabel* label = qobject_cast<QLabel*>(obj)) {
        if (event->type() == QEvent::MouseButtonPress) {
            QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
            if (mouseEvent->button() == Qt::RightButton) {
                qDebug() << "右键点击的是标签：" << label->toolTip(); // ✔ 使用了 label

                QMenu menu(this);
                QAction* openAction = menu.addAction("打开");
                QAction* action = menu.exec(mouseEvent->globalPosition().toPoint());

                if (action == openAction) {
                    qDebug() << "执行打开：" << label->toolTip();
                }
                return true;
            }
        }
    }


    return QMainWindow::eventFilter(obj, event);
}

void MainWindow::handlePageEdit()
{
    // ui->page_lineEdit->setStyleSheet("QLineEdit { border: 3px solid red; }"); // focusOut测试
    // ui->page_lineEdit->repaint(); // 强制重绘试试看

    QString text = ui->page_lineEdit->text().trimmed();
    bool ok = false;
    int page = text.toInt(&ok);

    if (ok && page >= 1 && page <= totalPages) {
        if ((page - 1) != currentIndex) {
            setPage(page - 1); // ✅ 跳转
        }
        ui->page_lineEdit->hide();
        ui->pageLabel->show();
    } else {
        // ❌ 输入非法，闪烁红色边框提示
        ui->page_lineEdit->setStyleSheet(R"(
            QLineEdit {
                border: 1px solid red;
                background: white;
                font-size: 22px;
                padding: 2px;
                border-radius: 4px;
            }
        )");
        // 自动显示 tooltip（立即弹出）：
        QToolTip::showText(ui->page_lineEdit->mapToGlobal(QPoint(0, ui->page_lineEdit->height())),
                           ui->page_lineEdit->toolTip(),
                           ui->page_lineEdit);
        qDebug() << "❌ 输入非法，闪烁红色边框提示; 输入1-15之间的数字";

        // 延时恢复原样式并恢复 label
        QTimer::singleShot(200, this, [this]() {
            ui->page_lineEdit->setStyleSheet(R"(
        QLineEdit {
            font-size: 24px;
            background-color: rgba(255, 255, 255, 0.9);
            padding: 3px 5px;
            height: 15px;
            border: 2px solid rgba(0, 161, 214, 0.8);
            border-radius: 6px;
            font-weight: bold;
            color: #080000;
            selection-background-color: rgba(0, 161, 214, 0.5);
            selection-color: white;
        }
        QLineEdit:focus {
            border-color: rgba(0, 161, 214, 1);
            background-color: white;
            outline: none;
        }
    )");
        });
        qDebug() << "恢复为 label";
    }
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    // 创建一个 QPainter 对象，绑定到当前窗口（this），用于绘制操作
    QPainter painter(this);

    // 判断缓存的图片是否为空（是否成功加载过图片）
    if (cachedPixmap.isNull()) {
        // 如果缓存图片为空，使用黑色填充整个窗口背景区域
        painter.fillRect(rect(), Qt::black);
    } else {
        // 如果缓存图片有效，则将图片绘制到整个窗口区域
        // 参数说明：
        // rect() 返回窗口的矩形区域，即目标绘制区域
        // cachedPixmap 是当前缓存的图片
        // cachedPixmap.rect() 是图片的源矩形区域（整个图片）

        // drawPixmap 会把源图片拉伸或压缩到目标矩形区域，默认不保持原始比例
        // 因此图片会被强制铺满整个窗口区域，可能产生拉伸变形
        painter.drawPixmap(rect(), cachedPixmap, cachedPixmap.rect());
    }

    // 调用父类的 paintEvent，确保窗口及子控件正常绘制
    QMainWindow::paintEvent(event);
}

void MainWindow::launchEmulator(){
    QString emulatorExe = appPath;
    if(emulatorExe.isEmpty()){
        QMessageBox::warning(this, "错误", "模拟器路径不正确");
        return;
    }

    // 创建并启动进程
    QProcess *process = new QProcess(this);
    process->start(emulatorExe);

    if(!process->waitForStarted()){
        qWarning() << "模拟器启动失败:" << process->errorString();
        QMessageBox::warning(this, "错误", "无法启动模拟器");
    }else{
        this->setWindowTitle("Chs-Game300 - Mesen");
        qDebug() << "打开Mesen";
    }
}

void MainWindow::launchEmulator(const QString &romPath) {

    QString emulatorExe = appPath; // 真实路径替换
    if(emulatorExe.isEmpty()){
        QMessageBox::warning(this, "错误","模拟器路径不正确");
        return;
    }

    QProcess *process = new QProcess(this);// 示例: 这里用 QProcess 启动外部模拟器程序，并传入rom路径作为参数
    process->start(emulatorExe, QStringList() << romPath);

    if (!process->waitForStarted()) {
        qWarning() << "模拟器启动失败:" << process->errorString();
        QMessageBox::warning(this, "错误", "无法启动模拟器");
        return;
    }else{
         // 显示加载的ROM文件名
        QFileInfo fileInfo(romPath);
        QString fileName = fileInfo.fileName(); // 提取不带路径的文件名
        this->setWindowTitle("Chs-Game300 - " + fileName);
        qDebug() << "启动加载了" << fileName;
    }

    QString labelText = getRomNameFromPath(romPath);
    qDebug() << labelText << "labelText";
    recentLabels.removeAll(labelText); // 去重
    recentLabels.prepend(labelText);   // 加入前部
    saveSettings();                    // 存储设置
    buildRecentLabelsMenu(recentLabelsMenu); // 重建菜单
}

QString MainWindow::getRomNameFromPath(const QString& romPath) {
    QFileInfo fileInfo(romPath);
    QString fileName = fileInfo.fileName();      // 带后缀完整文件名

    // 静态正则表达式，编译一次提高效率
    static const QRegularExpression prefixRegex("^\\d+-\\d+\\s*");  // 移除数字-数字空格前缀
    static const QRegularExpression suffixRegex("\\.nes$", QRegularExpression::CaseInsensitiveOption);

    QString displayName = fileName;
    displayName.remove(prefixRegex);
    displayName.remove(suffixRegex);

    return displayName;
}


void MainWindow::startGame()
{
    loadSettings();

    // 如果菜单已存在，清空后复用；避免重复创建
    if (!recentLabelsMenu) {
        recentLabelsMenu = new QMenu(this);
        ui->actionRecentLabels->setMenu(recentLabelsMenu);
    } else {
        recentLabelsMenu->clear();
    }
    buildRecentLabelsMenu(recentLabelsMenu);

    // 遍历所有标签
    for (size_t i = 0; i < labels.size(); ++i) {
        ClickLabel* clickLabel = qobject_cast<ClickLabel*>(labels[i]);
        if (!clickLabel) {
            qWarning() << "标签转换 ClickLabel 失败！";
            continue;
        }

        // 断开之前可能存在的连接，防止重复连接
        disconnect(clickLabel, &ClickLabel::clicked, nullptr, nullptr);
        disconnect(clickLabel, &ClickLabel::hovered, nullptr, nullptr);


        // 点击启动游戏
        connect(clickLabel, &ClickLabel::clicked, this, [this, i]() {
            int romIndex = i + currentIndex * 10;
            if (romIndex < 0 || romIndex >= romFilePaths.size()) return;

            const QString& romPath = romFilePaths[romIndex];
            qDebug() << "点击标签，启动游戏：" << romPath;
            launchEmulator(romPath);
        });

        // 悬浮播放音效（轻音）
        connect(clickLabel, &ClickLabel::hovered, this, [this]() {
            playPooledSound();
        });

        // 点击播放音效（确认音）
        connect(clickLabel, &ClickLabel::clicked, this, [this]() {
            playSoundByIndex(2);
        });
    }

    ui->actionRememberlastPage->setCheckable(true);
    ui->actionRememberlastPage->setChecked(rememberlastPage);
    connect(ui->actionRememberlastPage, &QAction::toggled, this, &MainWindow::toggleRememberLastPage);
}

// 初始化音效资源，包括 QMediaPlayer（适合完整播放）和 QSoundEffect（适合短音效池化播放）
// 参数：
//   mediaPaths      - 多个完整音效的路径列表（用于 QMediaPlayer）
//   poolSoundPath   - 要用于池化播放的短音效路径（用于 QSoundEffect）
//   poolSize        - 短音效池的大小（对象个数）
//   volume          - 所有音效的统一音量（0.0 ~ 1.0）
void MainWindow::initSoundEffects(const QStringList& mediaPaths,
                                  const QString& poolSoundPath,
                                  int poolSize,
                                  float volume)
{
    // 【1】清空旧的 QSoundEffect 音效池，释放资源，避免内存泄漏
    qDeleteAll(soundEffectPool);      // 逐个 delete 指针
    soundEffectPool.clear();          // 清空容器

    // 【2】清空旧的 QMediaPlayer 音效列表
    for (auto& item : soundEffects) {
        delete item.player;           // 删除播放器
        delete item.output;           // 删除音频输出设备
    }
    soundEffects.clear();

    // 【3】初始化 QMediaPlayer 播放器（播放完整音效，如启动音、过场音等）
    for (const QString& path : mediaPaths) {
        auto* player = new QMediaPlayer(this);       // 创建播放器，绑定到主窗口
        auto* output = new QAudioOutput(this);       // 创建音频输出设备
        output->setVolume(volume);                   // 设置音量
        player->setAudioOutput(output);              // 将输出设备连接到播放器
        player->setSource(QUrl(path));               // 设置音频资源路径
        soundEffects.append({ player, output });     // 存入播放器列表
    }

    // 【4】初始化 QSoundEffect 音效池（适合快速重复播放的短 UI 音，如点击、悬停等）
    QUrl poolSoundUrl(poolSoundPath);                // 将路径转换为 QUrl 格式
    for (int i = 0; i < poolSize; ++i) {
        auto* effect = new QSoundEffect(this);       // 创建音效对象
        effect->setSource(poolSoundUrl);             // 设置统一的音效资源
        effect->setVolume(volume);                   // 设置音量
        soundEffectPool.append(effect);              // 加入池中
    }

    // 【5】重置池索引，准备从第一个音效开始轮转播放
    currentPoolIndex = 0;
}


void MainWindow::playSoundByIndex(int index) {
    if (index < 0 || index >= soundEffects.size()) return;

    auto& item = soundEffects[index];
    if (item.player->playbackState() == QMediaPlayer::PlayingState)
        item.player->stop();

    item.player->play();
}

void MainWindow::playPooledSound() {
    if (soundEffectPool.isEmpty()) return;

    auto* effect = soundEffectPool[currentPoolIndex];

    if (effect->isPlaying())
        effect->stop();

    effect->play();
    currentPoolIndex = (currentPoolIndex + 1) % soundEffectPool.size();
}



void MainWindow::initImagePaths()
{
    imagePaths.clear();

    const int imageCount = 5;

    // 优先尝试从 Qt 资源加载
    for (int i = 1; i <= imageCount; ++i) {
        QString path = QString(":/img/vcd300-%1.JPG").arg(i, 2, 10, QChar('0'));
        QPixmap testPixmap(path);
        if (!testPixmap.isNull()) {
            imagePaths.append(path);
        } else {
            qWarning() << "图片资源加载失败：" << path;
        }
    }

    // 如果 QRC 加载失败，允许用户选择文件夹
    if (imagePaths.isEmpty()) {
        QMessageBox::warning(this, "图片资源加载失败",
                             "默认 Qt 资源路径未找到任何图片。\n请手动选择图片所在的文件夹。");

        QString dir = QFileDialog::getExistingDirectory(
            this, "请选择图片所在目录", QCoreApplication::applicationDirPath());

        if (dir.isEmpty()) {
            QMessageBox::critical(this, "加载失败", "未选择任何目录，无法加载图片！");
            return;
        }

        // 查找该目录下的匹配图片
        QDir imageDir(dir);
        QStringList files = imageDir.entryList(
            QDir::Files | QDir::NoSymLinks, QDir::Name);

        // 使用正则匹配所有 vcd300-*.jpg/jpeg 文件（忽略大小写）
        QRegularExpression pattern("^vcd300-\\d{2}\\.(jpg|jpeg)$",
                                   QRegularExpression::CaseInsensitiveOption);
        for (const QString& file : files) {
            if (pattern.match(file).hasMatch()) {
                imagePaths.append(imageDir.filePath(file));
            }
        }

        if (imagePaths.isEmpty()) {
            QMessageBox::critical(this, "加载失败", "选择的目录中未找到匹配的图片！");
            return;
        }
    }

    currentIndex = 0;
    showCurrentImage();
}


void MainWindow::showCurrentImage() // 显示当前图片页码（标签更新）
{
    ui->firstButton->setVisible(currentIndex > 1 && currentIndex < totalPages - 1);         // 不是第1，2，15页时显示“首页”
    ui->lastButton->setVisible(currentIndex < totalPages - 2 && currentIndex > 0);          // 不是第1，14，15时显示“尾页”
    // 如果图片路径列表为空，清空缓存并返回
    if (imagePaths.isEmpty()) {
        cachedPixmap = QPixmap();
        update(); // 触发 paintEvent 重绘
        return;
    }
    int imageIndex = currentIndex % imagePaths.size();
    // 从当前索引获取对应图片路径，加载为 QPixmap
    QPixmap pix(imagePaths.at(imageIndex));

    // 如果加载失败（pix 是空的），输出警告信息，并清空缓存
    if (pix.isNull()) {
        qWarning() << "图片加载失败：" << imagePaths.at(imageIndex);
        cachedPixmap = QPixmap();  // 加载失败，清空缓存
    } else {
        // 否则，加载成功，将其存入缓存 cachedPixmap，用于后续绘制
        cachedPixmap = pix;
    }
    update(); // 触发 paintEvent 重绘

    // 更新显示页码（假设 ui->pageLabel 是 QLabel）
    ui->pageLabel->setText(QString("%1").arg(currentIndex + 1));
    initLabel(labels);
}

void MainWindow::initAppPaths()
{
    QSettings settings(QCoreApplication::applicationDirPath() + "/config.ini", QSettings::IniFormat);

    // 读取已保存路径（可能为空）
    QString savedEmulatePath = settings.value("Paths/emuPath").toString();
    QString savedRomPath = settings.value("Paths/romFolder").toString();

    // 默认路径（程序目录下）
    QString defaultBasePath = QApplication::applicationDirPath();
    QString defaultemuPath = defaultBasePath + "/Mesen/Mesen.exe";
    QString defaultRomPath = defaultBasePath + "/Chs-Game300";

    // --- 模拟器路径选择 ---
    if (!savedEmulatePath.isEmpty() && QFile::exists(savedEmulatePath)) {
        // 用保存的有效路径
        appPath = savedEmulatePath;
        basePath = QFileInfo(appPath).absolutePath();
    } else if (QFile::exists(defaultemuPath)) {
        // 用默认路径
        appPath = defaultemuPath;
        basePath = QFileInfo(appPath).absolutePath();
        // 保存默认路径
        settings.setValue("Paths/emuPath", appPath);
        settings.sync();
    } else {
        // 都无效，弹窗让用户选
        QMessageBox::warning(this, "提示", "未找到 Mesen 模拟器，请手动选择 Mesen.exe");

        QString exePath = QFileDialog::getOpenFileName(this, "请选择 Mesen 模拟器 (Mesen.exe)", defaultBasePath, "可执行文件 (*.exe)");
        if (exePath.isEmpty()) {
            QMessageBox::critical(this, "错误", "未选择模拟器，程序无法运行！");
            return;
        }
        appPath = exePath;
        basePath = QFileInfo(appPath).absolutePath();

        // 保存用户选择路径
        settings.setValue("Paths/emuPath", appPath);
        settings.sync();
    }

    // --- ROM文件夹路径选择 ---
    if (!savedRomPath.isEmpty() && QDir(savedRomPath).exists()) {
        filePath = savedRomPath;
    } else if (QDir(defaultRomPath).exists()) {
        filePath = defaultRomPath;
        // 保存默认路径
        settings.setValue("Paths/romFolder", filePath);
        settings.sync();
    } else {
        QMessageBox::warning(this, "提示", "未找到 ROM 文件夹，请手动选择 Chs-Game300 文件夹");

        QString folderPath = QFileDialog::getExistingDirectory(this, "请选择 ROM 文件夹（Chs-Game300）", defaultBasePath);
        if (folderPath.isEmpty()) {
            QMessageBox::critical(this, "错误", "未选择 ROM 文件夹，程序无法运行！");
            return;
        }
        filePath = folderPath;

        // 保存用户选择路径
        settings.setValue("Paths/romFolder", filePath);
        settings.sync();
    }

    // 输出调试
    qDebug() << "[路径配置完成]";
    qDebug() << "Base Path:" << basePath;
    qDebug() << "Mesen Path:" << appPath;
    qDebug() << "ROM Folder:" << filePath;
}



void MainWindow::loadRomFilePaths(){
    // 创建一个目录对象，指向 ROM 文件所在的目录
    QDir romDir(filePath);

    // 获取该目录下所有扩展名为 .nes 的文件信息列表（仅限文件，不包括目录）
    QFileInfoList fileInfos = romDir.entryInfoList(QStringList() << "*.nes", QDir::Files);
    // 把这个正则表达式对象声明成静态的，让它只创建一次，后续复用，避免重复开销。
    static const QRegularExpression re(R"(^(\d+))"); // 匹配文件名开头的一串数字，例如 "123游戏.nes" 提取出 123;
    // 使用 std::sort 和正则表达式对文件名进行排序，依据是文件名开头的数字部分
    std::sort(fileInfos.begin(), fileInfos.end(), [](const QFileInfo &a, const QFileInfo &b) {
        // 匹配第一个文件名的数字部分
        QRegularExpressionMatch matchA = re.match(a.baseName());
        // 匹配第二个文件名的数字部分
        QRegularExpressionMatch matchB = re.match(b.baseName());

        // 将匹配到的数字字符串转换为整数，未匹配到则默认为 0
        int numA = matchA.hasMatch() ? matchA.captured(1).toInt() : 0;
        int numB = matchB.hasMatch() ? matchB.captured(1).toInt() : 0;

        if (numA == numB) {
            // 去掉前缀的数字-，再按后面的名称排序;汉字的 Unicode 顺序排序的
            QString nameA = a.baseName();
            QString nameB = b.baseName();
            nameA.remove(re);  // 去掉前缀数字
            nameB.remove(re);
            return nameA < nameB;
        }

        // 返回比较结果（升序排序）
        return numA < numB;
    });
    romFilePaths.clear();

    // 遍历排序后的文件信息列表，提取绝对路径并添加到 romFilePaths 中
    const QFileInfoList &fileListRef = fileInfos; // 引用已有的文件信息列表，避免拷贝，提高效率;避免Qt 容器的写时拷贝（copy-on-write）机制
    for (const QFileInfo &info : fileListRef) {     // 遍历文件信息列表中的每一个 QFileInfo 对象
        romFilePaths.append(info.absoluteFilePath());     // 获取当前文件的绝对路径（字符串），并添加到字符串列表 romFilePaths 中
    }
}

void MainWindow::initLabel(const std::vector<QLabel*> &labels)
{
    // int fileCount = std::min(static_cast<int>(romFilePaths.size()), static_cast<int>(labels.size()));
    // qDebug() << "fileCount: " << fileCount;
    // qDebug() << romFilePaths.size();
    totalPages = romFilePaths.size() / 10;
    // 用范围 for 循环结合索引遍历前 count 个元素
    int index = 10*currentIndex;
    for (QLabel* label : labels) {
        if (index < romFilePaths.size()) {
            QString fileName = getRomNameFromPath(romFilePaths[index]);

            // 获取 label 原来的编号文本，例如 "1."
            QString labelPrefix = QString("%1.").arg(index%10 + 1);  // 纯文本
            // 拼接最终显示内容
            QString displayText = labelPrefix + fileName;

            // 获取 label 当前字体的度量信息
            QFontMetrics fm(label->font());
            // qDebug() << label->width();

            // 根据 label 的宽度截断文本（加省略号）
            QString elidedText = fm.elidedText(displayText, Qt::ElideRight, 220 + 10); // 过长名字显示...
            label->setText(elidedText);
            label->setProperty("romPath", romFilePaths[index]);
            label->setToolTip(displayText); // 设置 tooltip 提示完整文件名
            // qDebug() << "Label text:" << label->text();  // 检查是否设置成功

            label->setContextMenuPolicy(Qt::CustomContextMenu);
            connect(label, &QLabel::customContextMenuRequested,
                    this, &MainWindow::onLabelRightClicked);
        } else {
            // 路径不足时，清空剩余的 label
            label->clear();
        }
        ++index;
    }
}

void MainWindow::onLabelRightClicked(const QPoint &pos)
{
    QLabel* label = qobject_cast<QLabel*>(sender());
    if (!label) return;

    // 弹出菜单
    QMenu contextMenu(this);
    QAction* openAction = contextMenu.addAction("打开");
    QAction* locationAction = contextMenu.addAction("定位文件位置");
    QAction* deleteAction = contextMenu.addAction("删除");
    QAction* searchAction = contextMenu.addAction("搜索此游戏");

    // 弹出菜单位置：全局映射
    QAction* selectedAction = contextMenu.exec(label->mapToGlobal(pos));
    if (!selectedAction) return;
    QString romPath = label->property("romPath").toString(); // 获取路径
    QFileInfo fileInfo(romPath);    // 文件信息
    if (selectedAction == openAction) {
        qDebug() << "打开：" << romPath;
        launchEmulator(romPath);
    } else if (selectedAction == locationAction) {
        qDebug() << "定位所在位置：" << label->toolTip();
        if (fileInfo.exists()) {
            qDebug() << "定位文件：" << romPath;

#ifdef Q_OS_WIN
            QString winPath = QDir::toNativeSeparators(romPath);
            qDebug() << "调用 ShellExecute 定位：" << winPath;

            // 使用 ShellExecute 选中文件
            LPCWSTR param = reinterpret_cast<LPCWSTR>(QString("/select,\"%1\"").arg(winPath).utf16());
            ShellExecuteW(nullptr, L"open", L"explorer.exe", param, nullptr, SW_SHOWNORMAL);
#elif defined(Q_OS_MAC)
            // macOS: 使用 open -R 选中文件
            QProcess::startDetached("open", { "-R", romPath });
#elif defined(Q_OS_LINUX)
            // Linux: 用 xdg-open 打开所在目录（不一定能选中文件）
            QString folder = fileInfo.absolutePath();
            QProcess::startDetached("xdg-open", { folder });
#endif
        } else {
            QMessageBox::warning(this, "文件不存在", "目标文件不存在，可能已被移动或删除。");
        }
    } else if (selectedAction == deleteAction) {
        qDebug() << "删除：" << label->toolTip();
        int ret = QMessageBox::question(this, "删除 ROM",
                                        QString("确定要删除\n%1\n吗？").arg(romPath),
                                        QMessageBox::Yes | QMessageBox::No);

        if (ret == QMessageBox::Yes) {
            if (QFile::remove(romPath)) {
                qDebug() << "删除成功：" << romPath;

                // 从路径列表中移除
                romFilePaths.removeAll(romPath);

                // 可选：重新刷新标签
                initLabel(labels);
            } else {
                QMessageBox::warning(this, "删除失败", "无法删除该文件！");
                }
        }
    }
    // 搜索此游戏
    if (selectedAction == searchAction) {
        QString searchText = label->text();

        // 去除开头的数字和点，格式类似 "5." 或 "10."
        static const QRegularExpression prefixRegex("^\\d+\\.\\s*");
        searchText.remove(prefixRegex);
        // 继续编码和搜索
        QString encodedText = QUrl::toPercentEncoding(searchText);
        QString baiduUrl = QString("https://www.baidu.com/s?wd=%1").arg(encodedText);
        QDesktopServices::openUrl(QUrl(baiduUrl));
        return;
    }
}

/**
 * 构建页面选择菜单，支持分页显示大量页面
 * @param fileMenu 要添加页面菜单的父菜单
 * @param totalPages 总页面数
 */
void MainWindow::buildPageMenu(QMenu* fileMenu, int totalPages)
{
    // 最大可见页数，超过此数量将显示"更多"子菜单
    const int MAX_VISIBLE_PAGES = 15;

    // 清除旧的页面子菜单（如果存在）
    // 避免重复添加，确保每次构建都是最新的页面列表
    if (pageSubMenu) {
        fileMenu->removeAction(pageSubMenu->menuAction());
        delete pageSubMenu;
    }

    // 创建新的"页面"子菜单
    pageSubMenu = new QMenu("页面", this);

    // 计算需要直接显示的页数（取较小值）
    int showPages = qMin(MAX_VISIBLE_PAGES, totalPages);

    // 添加可见页面范围的菜单项
    for (int i = 1; i <= showPages; ++i) {
        QAction* action = pageSubMenu->addAction(QString::number(i));
        // 使用lambda表达式捕获页码，点击时调用setPage函数
        // 注意：setPage接收的是0-based索引，所以需要减1
        connect(action, &QAction::triggered, this, [this, i]() {
            setPage(i - 1);
        });
    }

    // 如果总页数超过最大可见数，添加"更多"菜单项
    if (totalPages > MAX_VISIBLE_PAGES) {
        QAction* moreAction = pageSubMenu->addAction("...");
        QMenu* moreMenu = new QMenu("更多页面", this);

        // 构建"更多"子菜单，显示剩余的页面
        for (int i = MAX_VISIBLE_PAGES + 1; i <= totalPages; ++i) {
            QAction* action = moreMenu->addAction(QString::number(i));
            connect(action, &QAction::triggered, this, [this, i]() {
                setPage(i - 1);
            });
        }

        // 将"更多"子菜单关联到"..."菜单项
        moreAction->setMenu(moreMenu);
    }

    // 将构建好的页面菜单添加到指定的父菜单中
    fileMenu->addMenu(pageSubMenu);
}

void MainWindow::printDebugInfo()
{
    // 调试输出
    qDebug() << "App Path:" << appPath;
    qDebug() << "File Path:" << filePath;
    qDebug() << "实际添加图片数：" << imagePaths.size();
}

// 保存配置
void MainWindow::saveSettings()
{
    QString configPath = QCoreApplication::applicationDirPath() + "/config.ini";
    QSettings settings(configPath, QSettings::IniFormat);

    // 检查文件是否可写
    QFile file(configPath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
        qWarning() << "无法写入配置文件:" << configPath;
        return;
    }
    file.close();

    // 保存基础设置
    settings.setValue("General/rememberLastPage", rememberlastPage);
    if (rememberlastPage) {
        settings.setValue("General/lastPage", currentIndex);
    }

    // 保存最近打开的标签（去重并限制数量）
    QStringList uniqueLabels;
    QSet<QString> seenLabels;

    for (auto it = recentLabels.constBegin(); it != recentLabels.constEnd(); ++it) {
        const QString& label = *it;
        if (!seenLabels.contains(label)) {
            seenLabels.insert(label);
            uniqueLabels.append(label);
        }
    }

    // 截取前10项
    QStringList recentLabelsToSave = uniqueLabels.mid(0, qMin(10, uniqueLabels.size()));
    settings.setValue("RecentLabels/list", recentLabelsToSave);

    // 保存其他可能的配置项
    settings.setValue("UI/windowWidth", this->width());
    settings.setValue("UI/windowHeight", this->height());

    // 检查保存状态
    if (settings.status() != QSettings::NoError) {
        qWarning() << "保存配置文件时出错:" << settings.status();
    }
}

// 读取配置
void MainWindow::loadSettings()
{
    QString configPath = QCoreApplication::applicationDirPath() + "/config.ini";
    QSettings settings(configPath, QSettings::IniFormat);

    // 读取基础设置
    rememberlastPage = settings.value("General/rememberLastPage", false).toBool();

    if (rememberlastPage) {
        int lastPage = settings.value("General/lastPage", 0).toInt();
        setPage(lastPage);
    }

    // 加载最近打开的标签
    recentLabels = settings.value("RecentLabels/list", QStringList()).toStringList();

    // 恢复窗口大小（可选）
    int windowWidth = settings.value("UI/windowWidth", 800).toInt();
    int windowHeight = settings.value("UI/windowHeight", 600).toInt();
    this->resize(windowWidth, windowHeight);

    // 重建页面菜单
    buildPageMenu(ui->menu, totalPages);

    // 检查读取状态
    if (settings.status() != QSettings::NoError) {
        qWarning() << "读取配置文件时出错:" << settings.status();
    }
}

/**
 * 构建最近标签菜单（最多显示10个标签），直接显示在父菜单中
 * @param parentMenu 要添加标签菜单的父菜单
 */
void MainWindow::buildRecentLabelsMenu(QMenu* parentMenu)
{
    if (!parentMenu) return; // 防御性编程：检查空指针

    const int MAX_DISPLAY_LABELS = 10;

    // 保存原始菜单项以便后续清理
    const QList<QAction*> originalActions = parentMenu->actions();

    // 创建一个列表保存需要移除的菜单项
    QList<QAction*> actionsToRemove;

    // 识别需要移除的菜单项（使用自定义属性标记）
    for (QAction* action : originalActions) {
        if (action->property("isRecentLabel").toBool() ||
            action->text() == "清除历史") {
            actionsToRemove.append(action);
        }
    }

    // 安全地移除菜单项
    for (QAction* action : std::as_const(actionsToRemove)) {
        parentMenu->removeAction(action);
        delete action;
    }

    // 添加分隔线并标记为最近标签菜单项
    QAction* separator = parentMenu->addSeparator();
    separator->setText("------");
    separator->setProperty("isRecentLabel", true);

    // 如果没有最近标签，显示占位提示
    if (recentLabels.isEmpty()) {
        QAction* emptyAction = parentMenu->addAction("无最近游戏");
        emptyAction->setEnabled(false);
        emptyAction->setProperty("isRecentLabel", true);
    }
    else {
        // 显示最近使用的标签
        int displayCount = qMin(MAX_DISPLAY_LABELS, recentLabels.size());
        for (int i = 0; i < displayCount; ++i) {
            const QString& label = recentLabels[i];
            QAction* action = parentMenu->addAction(label);
            action->setProperty("isRecentLabel", true);
            action->setData(QVariant::fromValue(QPair<int, QString>(i, label)));

            connect(action, &QAction::triggered, this, [this, label, parentMenu]() {
                onRecentLabelSelected(label);
                buildRecentLabelsMenu(parentMenu);
            });
        }

        // 添加清除历史菜单项
        QAction* clearAction = parentMenu->addAction("清除历史");
        clearAction->setIcon(QIcon::fromTheme("edit-clear"));

        connect(clearAction, &QAction::triggered, this, [this, parentMenu]() {
            // 清空最近标签列表
            recentLabels.clear();

            // 保存设置
            saveSettings();

            // 刷新菜单显示
            buildRecentLabelsMenu(parentMenu);

            // 显示操作成功消息
            if (statusBar()) {
                statusBar()->showMessage("已清除最近标签", 3000);
            }
        });
    }
}

/**
 * 处理最近标签点击事件
 * @param label 被点击的标签文本
 */
void MainWindow::onRecentLabelSelected(const QString& label)
{
    // 更新标签使用历史（将当前标签移到最前面）
    recentLabels.removeAll(label); // 去重
    recentLabels.prepend(label);

    // 保存设置
    saveSettings();

    // 执行与标签相关的操作
    processLabel(label);
}

/**
 * 处理标签的具体操作
 * @param label 标签文本
 */
void MainWindow::processLabel(const QString& label)
{
    qDebug() << "[匹配标签]：" << label;

    // 尝试查找匹配的 ROM
    QStringList matched;

    // 统一清理函数
    auto cleanName = [](const QString& text) -> QString {
        static const QRegularExpression specialCharsRegex("[\\d\\.\\s\\(\\)]");
        static const QRegularExpression bracketsRegex("\\[.*\\]|\\(.*\\)");
        QString cleaned = text;
        cleaned.remove(specialCharsRegex);
        cleaned.remove(bracketsRegex);
        return cleaned;
    };

    QString cleanedLabel = cleanName(label);

    for (const QString& path : romFilePaths) {
        QFileInfo info(path);
        QString fileName = info.fileName();
        QString baseName = info.baseName();
        QString cleanedBase = cleanName(baseName);

        if (fileName.contains(label, Qt::CaseInsensitive) ||
            cleanedBase.contains(cleanedLabel, Qt::CaseInsensitive)) {
            matched << path;
        }
    }

    // 根据匹配数量判断行为
    if (matched.size() == 1) {
        qDebug() << "✅ 自动匹配并启动：" << matched.first();
        launchEmulator(matched.first());
    } else {
        // 弹出搜索窗口（让用户选）
        SearchDialog* dialog = new SearchDialog(romFilePaths, this);
        dialog->setWindowTitle(QString("未唯一匹配 \"%1\"，请选择").arg(label));
        connect(dialog, &SearchDialog::romSelected, this, [this](const QString& path) {
            qDebug() << "🔎 手动选择并启动：" << path;
            launchEmulator(path);
        });
        dialog->exec();
    }
}




void MainWindow::on_prevButton_clicked()
{
    if (totalPages <= 1) return;

    currentIndex = (currentIndex - 1 + totalPages) % totalPages;
    showCurrentImage();
    playSoundByIndex(0);// 播放第 0 个音效（如 click）
}


void MainWindow::on_nextButton_clicked()
{
    if (totalPages <= 1) return;

    currentIndex = (currentIndex + 1) % totalPages;
    showCurrentImage();
    playSoundByIndex(0);// 播放第 0 个音效（如 click）
}


void MainWindow::on_lastButton_clicked()
{
    currentIndex = totalPages-1;
    showCurrentImage();
    playSoundByIndex(0);// 播放第 0 个音效（如 click）
}


void MainWindow::on_firstButton_clicked()
{
    currentIndex = 0;
    showCurrentImage();
    playSoundByIndex(0);// 播放第 0 个音效（如 click）
}


void MainWindow::on_actionOpen_triggered()
{
    // 打开文件选择对话框，允许选择文本文件
    QString filePath = QFileDialog::getOpenFileName(
        this,                   // 父窗口指针
        "打开文件",             // 对话框标题
        "/Chs-Game300",                     // 默认打开路径
        "nes文件 (*.nes);;zip文件 (*.zip);;rar文件 (*.rar)" // 文件过滤器
        );
    launchEmulator(filePath);
}

void MainWindow::on_actionList_triggered()
{
    // 打开文件选择对话框，允许选择文本文件
    QString filePath = basePath + "/Chs-Game300/!readme读我.txt";

    if (!filePath.isEmpty()) {
        // 使用系统默认应用打开文件
        bool success = QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));

        if (!success) {
            QMessageBox::critical(this, "错误", "无法打开文件: " + filePath);
        }
    }
}

void MainWindow::on_actionRandom_triggered()
{
    if (romFilePaths.isEmpty())
        return;

    // 生成随机索引，类型保持一致
    const qsizetype randomIndex = QRandomGenerator::global()->bounded(romFilePaths.size());
    const QString& romPath = romFilePaths[randomIndex];

    qDebug() << "随机启动游戏：" << romPath;
    launchEmulator(romPath);

    // 提取文件名用于 recentLabels 显示
    QString fileName = QFileInfo(romPath).baseName();

    // 加入最近列表（去重 + 加入最前）
    recentLabels.removeAll(fileName);
    recentLabels.prepend(fileName);

    // 存储设置并重建菜单
    saveSettings();

    if (recentLabelsMenu)
        buildRecentLabelsMenu(recentLabelsMenu);
    else
        qWarning() << "recentLabelsMenu 未初始化";
}


void MainWindow::on_actionAbout_triggered()
{
    QString aboutText = R"(
        <h3>Chs-Game300</h3>
        <p><b>作者：</b>loushen</p>
        <p><b>版本：</b>1.0.0</p>
        <p><b>创建时间：</b>2025年6月24</p>
        <p><b>项目地址：</b>
        <a href='https://gitee.com/loushen/chs-game300--chinese-game-300.git' style='color:blue;'>Gitee - Chs-Game300</a></p>
        <p>该程序使用Qt Creator 16.0.2 Based on  Qt 6.8.3 (MSVC 2022, x86_64)</p>
    )";

    QMessageBox::about(this, "关于 Chs-Game300", aboutText);
}


void MainWindow::on_actionLog_triggered()
{
    LogViewerDialog* dialog = new LogViewerDialog(getLogBuffer(), this);    // 创建一个日志查看对话框对象，并将当前日志文本传入构造函数
    dialog->exec(); // dialog->exec();
}


void MainWindow::on_actionRandompage_triggered()
{
    QRandomGenerator rng = QRandomGenerator::securelySeeded(); // 用安全种子初始化
    int randomIndex = rng.bounded(totalPages);
    setPage(randomIndex);
}



void MainWindow::on_actionControl_triggered()
{
    QString imagePath = ":/img/control.png";
    QString infoText = "1p 默认按键。2p请到模拟器选项-->输入-->nes-->设置里更改"; //

    QDialog dialog(this);
    dialog.setWindowTitle("按键说明");

    QLabel* imageLabel = new QLabel(&dialog);
    QPixmap pixmap(imagePath);
    if (!pixmap.isNull()) {
        imageLabel->setPixmap(pixmap.scaledToWidth(600)); // 调整图片大小
    }

    QLabel* infoLabel = new QLabel(infoText, &dialog);
    QVBoxLayout* layout = new QVBoxLayout(&dialog);
    layout->addWidget(imageLabel);
    layout->addWidget(infoLabel);
    QPushButton* btn = new QPushButton("打开设置", &dialog);
    // 可选：设置按钮样式（使用Qt样式表）
    btn->setStyleSheet(
        "QPushButton {"
        "    background-color: #4CAF50;"  // 绿色背景
        "    color: white;"               // 白色文字
        "    border-radius: 5px;"         // 圆角
        "    font-size: 14px;"            // 字体大小
        "    min-width: 120px;"         // 最小宽度
        "    max-width: 200px;"         // 最大宽度
        "    min-height: 40px;"         // 最小高度
        "    max-height: 50px;"         // 最大高度
        "}"
        "QPushButton:hover {"
        "    background-color: #45a049;"  // 悬停时颜色变深
        "}"
        "QPushButton:pressed {"
        "    background-color: #3d8b40;"  // 按下时颜色更深
        "}"
        );
    layout->addWidget(btn);
    // 连接按钮的点击信号到槽函数（可选）

    connect(btn, &QPushButton::clicked, this,
            static_cast<void (MainWindow::*)()>(&MainWindow::launchEmulator));    // 显式指定函数指针类型
    dialog.setLayout(layout);
    dialog.exec();
}

// Windows API头文件
#ifdef Q_OS_WIN
#include <windows.h>
#include <shlobj.h>
#include <QTreeView>

#endif

void MainWindow::on_CreateDesktopShortcut_triggered()
{
    // 获取当前应用程序路径
    QString appPath = QCoreApplication::applicationFilePath();
    if (appPath.isEmpty()) {
        QMessageBox::critical(this, "错误", "无法获取当前程序路径");
        return;
    }

    QString appBaseName = QFileInfo(appPath).baseName();

    // 获取桌面路径（确保存在）
    QString desktopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
    if (desktopPath.isEmpty()) {
        desktopPath = QDir::homePath() + "/Desktop";
        if (!QDir().exists(desktopPath)) {
            QMessageBox::critical(this, "错误", "无法定位桌面路径");
            return;
        }
    }

    // 直接在桌面创建快捷方式，无需用户选择路径
    QString shortcutPath = desktopPath + "/" + appBaseName + ".lnk";

    // 创建快捷方式
    bool success = false;
    QString errorMsg;

#ifdef Q_OS_WIN
    // 初始化COM库
    HRESULT hr = CoInitialize(NULL);
    if (FAILED(hr)) {
        errorMsg = "无法初始化COM库";
    } else {
        // 创建ShellLink对象
        IShellLink* psl = NULL;
        hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
                              IID_IShellLink, (LPVOID*)&psl);

        if (SUCCEEDED(hr)) {
            // 设置快捷方式属性
            psl->SetPath(appPath.toStdWString().c_str());
            psl->SetDescription(QString("快捷方式 - %1").arg(appBaseName).toStdWString().c_str());
            psl->SetWorkingDirectory(QFileInfo(appPath).path().toStdWString().c_str());

            // 保存快捷方式
            IPersistFile* ppf = NULL;
            hr = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);

            if (SUCCEEDED(hr)) {
                hr = ppf->Save(shortcutPath.toStdWString().c_str(), TRUE);
                ppf->Release();
                success = SUCCEEDED(hr);
                if (!success) {
                    errorMsg = "无法保存快捷方式文件";
                }
            } else {
                errorMsg = "无法获取保存接口";
            }
            psl->Release();
        } else {
            errorMsg = "无法创建ShellLink对象";
        }
        CoUninitialize();
    }
#else
    errorMsg = "此功能仅支持Windows系统";
    success = false;
#endif

    // 显示结果
    if (success) {
        QMessageBox::information(this, "成功",
                                 QString("快捷方式已创建到桌面:\n%1").arg(shortcutPath));
    } else {
        QMessageBox::critical(this, "失败", errorMsg);
    }

}

void MainWindow::on_actionSearchFile_triggered()
{
    SearchDialog* dialog = new SearchDialog(romFilePaths, this);
    connect(dialog, &SearchDialog::romSelected, this, [this](const QString& path) {
        qDebug() << "搜索选择：" << path;
        launchEmulator(path);
    });
    dialog->exec();
}



void MainWindow::on_actionPathset_triggered()
{
    // 读取现有设置
    QSettings settings(QCoreApplication::applicationDirPath() + "/config.ini", QSettings::IniFormat);
    QString currentAppPath = settings.value("Paths/emuPath").toString();
    QString currentRomPath = settings.value("Paths/romFolder").toString();

    // 创建对话框
    QDialog dialog(this);
    dialog.setWindowTitle("路径设置");
    dialog.resize(500, 150);

    // 创建布局
    QVBoxLayout *mainLayout = new QVBoxLayout(&dialog);

    // APP路径选择
    QHBoxLayout *appPathLayout = new QHBoxLayout;
    QLabel *appPathLabel = new QLabel("应用程序路径:", &dialog);
    QLineEdit *appPathEdit = new QLineEdit(currentAppPath, &dialog);
    QPushButton *appPathButton = new QPushButton("浏览...", &dialog);
    appPathLayout->addWidget(appPathLabel);
    appPathLayout->addWidget(appPathEdit);
    appPathLayout->addWidget(appPathButton);
    mainLayout->addLayout(appPathLayout);

    // ROM路径选择
    QHBoxLayout *romPathLayout = new QHBoxLayout;
    QLabel *romPathLabel = new QLabel("ROM文件路径:", &dialog);
    QLineEdit *romPathEdit = new QLineEdit(currentRomPath, &dialog);
    QPushButton *romPathButton = new QPushButton("浏览...", &dialog);
    romPathLayout->addWidget(romPathLabel);
    romPathLayout->addWidget(romPathEdit);
    romPathLayout->addWidget(romPathButton);
    mainLayout->addLayout(romPathLayout);

    // 按钮区域
    QHBoxLayout *buttonLayout = new QHBoxLayout;
    QPushButton *okButton = new QPushButton("确定", &dialog);
    QPushButton *cancelButton = new QPushButton("取消", &dialog);
    buttonLayout->addStretch();
    buttonLayout->addWidget(okButton);
    buttonLayout->addWidget(cancelButton);
    mainLayout->addLayout(buttonLayout);

    connect(appPathButton, &QPushButton::clicked, this, [this, appPathEdit, currentAppPath]() {
        QFileDialog fileDialog(this, "选择应用程序文件", currentAppPath);

        // 设置视图模式为详细列表
        fileDialog.setViewMode(QFileDialog::Detail);

        // 显示所有文件和目录，包括隐藏文件
        fileDialog.setFilter(QDir::AllDirs | QDir::Files | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot);

        // 设置只允许选择文件
        fileDialog.setFileMode(QFileDialog::ExistingFile);

        // 设置文件过滤器
        fileDialog.setNameFilter("可执行文件 (*.exe *.app);;所有文件 (*)");

        if (fileDialog.exec() == QDialog::Accepted) {
            const QStringList &selectedFiles = fileDialog.selectedFiles();
            if (!selectedFiles.isEmpty()) {
                appPathEdit->setText(selectedFiles.first());
            }
        }
    });

    connect(romPathButton, &QPushButton::clicked, this, [this, romPathEdit, currentRomPath]() {
        QFileDialog fileDialog(this, "选择ROM文件目录", currentRomPath);

        // 设置为目录选择模式，但允许查看文件
        fileDialog.setFileMode(QFileDialog::Directory);
        fileDialog.setOption(QFileDialog::ShowDirsOnly, false); // 重要：允许显示文件

        // 设置视图模式为详细列表
        fileDialog.setViewMode(QFileDialog::Detail);

        // 显示所有文件和目录，包括隐藏文件
        fileDialog.setFilter(QDir::AllDirs | QDir::Files | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot);

        // 自定义文件对话框的视图
        if (QTreeView *treeView = fileDialog.findChild<QTreeView*>()) {
            treeView->setSortingEnabled(true); // 启用排序
            treeView->setSelectionMode(QAbstractItemView::SingleSelection);
        }

        // 设置默认视图为树形视图（可选）
        fileDialog.setOption(QFileDialog::DontUseNativeDialog, true);

        if (fileDialog.exec() == QDialog::Accepted) {
            const QStringList &selectedFiles = fileDialog.selectedFiles();
            if (!selectedFiles.isEmpty()) {
                romPathEdit->setText(selectedFiles.first());
            }
        }
    });

    connect(okButton, &QPushButton::clicked, &dialog, &QDialog::accept);
    connect(cancelButton, &QPushButton::clicked, &dialog, &QDialog::reject);

    // 显示对话框
    if (dialog.exec() == QDialog::Accepted) {
        QString newAppPath = appPathEdit->text().trimmed();
        QString newRomPath = romPathEdit->text().trimmed();

        // 验证应用程序文件是否存在 - 使用静态exists()函数
        if (!QFileInfo::exists(newAppPath) || !QFileInfo(newAppPath).isFile()) {
            QMessageBox::warning(this, "路径错误", "应用程序文件不存在!");
            return;
        }

        // 验证ROM目录是否存在
        if (!QDir(newRomPath).exists()) {
            QMessageBox::warning(this, "路径错误", "ROM文件目录不存在!");
            return;
        }

        // 保存设置
        settings.setValue("Paths/emuPath", newAppPath);
        settings.setValue("Paths/romFolder", newRomPath);
        appPath = newAppPath;
        filePath = newRomPath;
        loadRomFilePaths();
        initLabel(labels);
        // 通知用户
        QMessageBox::information(this, "设置成功", "路径设置已保存!");

        // 触发路径更改事件（可选）
        // emit pathSettingsChanged(newAppPath, newRomPath);
    }
}

